import { connect } from 'dva';
import * as THREE from 'three'
import { useEffect, useRef } from 'react';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
// 如果有需要解压的模型，需导入
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'

 const ModelPage = (props) => {
   const sceneRef = useRef(null)
   const cameraRef = useRef(null)
   const rendererRef = useRef(null)
   const guiRef = useRef(null)
   const width = 1000; //宽度
   const height = 800; //高度
   useEffect(()=>{
    init()
   }, [])
   const init = () => {
      // 0.添加GUI
      const eventObj = {
        Fullscreen: function(){
         document.body.requestFullscreen()
        },
        Exitscreen: () => {
          document.exitFullscreen()
        }
      }
      guiRef.current = new GUI()
      guiRef.current.add(eventObj, "Fullscreen").name('全屏')
      guiRef.current.add(eventObj, "Exitscreen").name('退出全屏')

      // 1.创建3D场景对象Scene
      sceneRef.current = new THREE.Scene();

      // 4.加载几何体/模型
      setGeometry()

      // 2. 定义虚拟相机部分
      setCamera()

      // 5. 坐标辅助器
      const axesHelper = new THREE.AxesHelper(500)
      sceneRef.current.add(axesHelper)

      // 3.渲染器
      setRenderer()

      // 全屏 rendererRef.current.domElement.requestFullscreen()
      window.addEventListener("resize",()=>{
        rendererRef.current.setSize(window.innerWidth,window.innerHeight);
        cameraRef.current.aspect = window.innerWidth/window.innerHeight;
        cameraRef.current.updateProjectionMatrix()
      })

   }

   // 创建相机
   const setCamera = () => {
      // width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
      cameraRef.current = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
      // 实例化一个透视投影相机对象
      // 根据需要设置相机位置具体值
      cameraRef.current.position.set(200, 100, 0);
      cameraRef.current.lookAt(0,0,0);//指向mesh对应的位置
   }
   // 创建几何体
   const setGeometry = () => {
      //  example 1：加载模型
      getModel()   
   }
   // 创建渲染器
   const setRenderer = () => {
      // 创建渲染器对象
      rendererRef.current = new THREE.WebGLRenderer({
        antialias: true, //抗锯齿
      });
      // 输出的环境编码
      rendererRef.current.outputEncoding = THREE.sRGBEncoding;
      rendererRef.current.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
      rendererRef.current.render(sceneRef.current, cameraRef.current); //执行渲染操作
      document.getElementById('webgl').appendChild(rendererRef.current.domElement);
      // 6. 轨道控制器
      const controls = new OrbitControls(cameraRef.current, rendererRef.current.domElement)

      function animate(){
        requestAnimationFrame(animate)
        controls.update() 
        // mesh.rotation.x += 0.01;
        // mesh.rotation.y += 0.01;
        rendererRef.current.render(sceneRef.current, cameraRef.current)
      }
      animate()
   }
   // 导入模型
   const getModel = () => {
      // 可以导入背景纹理当背景图，也可以背景色
      const loader = new THREE.TextureLoader();
      const bgTexture = loader.load(require('../assets/img2/bg-login.png'));
      bgTexture.mapping = THREE.EquirectangularRefractionMapping;
      sceneRef.current.background = bgTexture;
      sceneRef.current.environment = bgTexture;

      // 水晶材质需要环境光
      const ambient = new THREE.AmbientLight(0xffffff, 1);
      sceneRef.current.add(ambient)

      // sceneRef.current.background = new THREE.Color(0x999999)
      const gltfLoader = new GLTFLoader();
      gltfLoader.load(require('.././assets/model/test.glb'), (glb) => {
          console.log(glb)
          sceneRef.current.add(glb.scene)
          // 给一个物体设置Phong材质,设置水晶
          const translateMaterial = new THREE.MeshPhongMaterial({
            color: 0x00ff00,
            envMap: bgTexture,
            refractionRatio: 0.7,
            reflectivity: 0.99,
            opacity: 0.5,
          })
          const model = glb.scene;
          model.traverse((child)=>{
            if(child.isMesh){
                child.castShadow = true;
                child.receiveShadow = true;   
                if(child.name.includes("柱体")){
                    child.material = translateMaterial;
                }
                if(child.name.includes("fox") || child.name.includes("leaves")){
                    child.material = translateMaterial;
                }
            }
        }) 

          // 找模型中的几何体
          let childModel1 = glb.scene.getObjectByName('mushroom002')
          let geometry = childModel1.geometry;
          // 计算此几何体的包围盒,min/max 三维向量
          geometry.computeBoundingBox();
          geometry.center();
          let box = geometry.boundingBox;
          // 更新世界矩阵
          childModel1.updateWorldMatrix(true,true)
          // 更新包围盒
          box.applyMatrix4(childModel1.matrixWorld)
          // 获取包围盒的中心点
          let center = box.getCenter(new THREE.Vector3());
          // 创建包围盒辅助器
          const boxHelper = new THREE.Box3Helper(box, 0x6c06ea);
          sceneRef.current.add(boxHelper)

          // 获取包围球
          let sphere = geometry.boundingSphere;
          // 按比例缩放 设置世界矩阵
          sphere.applyMatrix4(childModel1.matrixWorld)
          const sphereHelper = new THREE.SphereGeometry(sphere.radius, 16, 16)
          let sphereMaterial = new THREE.MeshBasicMaterial({
            color: 0xff0000,
            wireframe: true, //网格模式
          })
          let sphereMesh = new THREE.Mesh(sphereHelper, sphereMaterial)
          sphereMesh.position.copy(sphere.center);
          sceneRef.current.add(sphereMesh)

          // 获取一个模型的边缘几何体(也可以自己画一个立方体)
          // 1. 拿一个现成的模型
          let childModel2 = glb.scene.getObjectByName('立方体006')
          let geometry2 = childModel2.geometry; 
          // 2. 创建其边缘几何体
          let edgeGeometry = new THREE.EdgesGeometry(geometry2);
          // 3. 创建线段材质 LineBasicMaterial
          const material2 = new THREE.LineBasicMaterial({
            color: 0x6c06ea,
            linewidth: 1,
            // linecap: 'round',
            // linejoin: 'round'
          })
          // 4. 创建线段 LineSegments
          let edges = new THREE.LineSegments(edgeGeometry, material2);
          childModel2.updateWorldMatrix(true,true)
          edges.matrix.copy(childModel2.matrixWorld);
          edges.matrix.decompose(edges.position,edges.quaternion,edges.scale)
          sceneRef.current.add(edges)
      })
   }


  return (
    <div>
      <h1>加载导入gltf,glb模型，创建包围盒，包围球，边缘几何体，线框几何体</h1>
      <div id="webgl" style={{marginTop: 10,marginLeft: 10}}></div>
    </div>
  );
}
export default connect(({common})=>({
  userInfo: common.userInfo,
}))(ModelPage)